﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using InkFx.WinControl.Core;

namespace InkFx.WinControl
{
    /// <summary>
    /// 表示组成应用程序的用户界面的窗口或对话框。
    /// </summary>
    [ToolboxItem(false)]
    public class SplitterForm : NoneForm
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="horizontal">Type: bool</param>
        /// <param name="rectRange">Type: Rectangle</param>
        /// <param name="rectSplit">Type: Rectangle</param>
        /// <param name="clip">Type: Region</param>
        public SplitterForm(bool horizontal, Rectangle rectRange, Rectangle rectSplit, Region clip)
        {
            base.BackColor = Color.Black; //Win32API.Transparent; //
            base.Opacity = 0.5;
            base.Enabled = false;

            this.m_ClipStart = clip;
            this.m_RectRange = rectRange;
            this.m_IsHorizontal = horizontal;
            this.m_RectStart = GetSplitRect(rectSplit);
            this.m_PointStart = System.Windows.Forms.Control.MousePosition;

            //if (this.RectStart.Width >= 10) Console.WriteLine("S: " + this.RectStart);
            //Console.WriteLine("S: " + this.RectStart);
            //Console.WriteLine("R: " + this.RectRange);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="owner">Type: System.Windows.Forms.Form</param>
        /// <param name="horizontal">Type: bool</param>
        /// <param name="rectRange">Type: Rectangle</param>
        /// <param name="rectSplit">Type: Rectangle</param>
        /// <param name="clip">Type: Region</param>
        /// <returns></returns>
        public static SplitterForm BeginSplitter(System.Windows.Forms.Form owner, bool horizontal, Rectangle rectRange, Rectangle rectSplit, Region clip)
        {
            SplitterForm form = new SplitterForm(horizontal, rectRange, rectSplit, clip);
            form.Show(owner);
            return form;
        }


        #region  字 段 属 性

        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_IsSplitMoving = false;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_IsHorizontal = false;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Region m_ClipStart = null;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectRange = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectStart = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Point m_PointStart = Point.Empty;

        
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public Region ClipStart
        {
            get { return m_ClipStart; }
        }
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public Rectangle RectRange
        {
            get { return m_RectRange; }
        }
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public Rectangle RectStart
        {
            get { return m_RectStart; }
        }
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public Point PointStart
        {
            get { return m_PointStart; }
        }


        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public bool IsSplitMoving
        {
            get { return m_IsSplitMoving; }
        }

        #endregion


        /// <summary>
        /// 
        /// </summary>
        public void ShowSplitter()
        {
            if (!this.IsHandleCreated || this.Disposing || this.IsDisposed) return;

            var point1 = this.m_PointStart;
            var point2 = System.Windows.Forms.Control.MousePosition;
            var diff = this.m_IsHorizontal ? new Point(point1.X, point2.Y - point1.Y) : new Point(point2.X - point1.X, point1.Y);
            var rect1 = this.m_RectStart;
            var rect2 = new Rectangle(rect1.X + diff.X, rect1.Y + diff.Y, rect1.Width, rect1.Height);
            this.ShowSplitter(rect2);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rectSplit">Type: Rectangle</param>
        public void ShowSplitter(Rectangle rectSplit)
        {
            if (!this.IsHandleCreated || this.Disposing || this.IsDisposed) return;
            
            this.Bounds = GetSplitRect(rectSplit);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rectSplit">Type: Rectangle</param>
        /// <param name="clip">Type: Region</param>
        public void ShowSplitter(Rectangle rectSplit, Region clip)
        {
            if (!this.IsHandleCreated || this.Disposing || this.IsDisposed) return;
            
            this.Bounds = GetSplitRect(rectSplit);
            SetRegion(clip);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public SplitInfo EndSplitter()
        {
            if (!this.IsHandleCreated || this.Disposing || this.IsDisposed) return SplitInfo.Empty;

            var info = this.GetSplitInfo();
            this.Close();
            this.Dispose();
            return info;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public SplitInfo GetSplitInfo()
        {
            if (!this.IsHandleCreated || this.Disposing || this.IsDisposed) return SplitInfo.Empty;

            var rectE = this.Bounds;
            var rectS = this.RectStart;
            //Console.WriteLine("End: " + (rectE != rectS) + " : " + rectS + " > " + rectE);
            return new SplitInfo(rectS, rectE);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="rect">Type: Rectangle</param>
        /// <returns></returns>
        public Rectangle GetSplitRect(Rectangle rect)
        {
            var rectM = this.RectRange;
            if (rectM.Width >= 1 || rectM.Height >= 1)
            {
                if (rect.X < rectM.X) rect.X = rectM.X;
                if (rect.Y < rectM.Y) rect.Y = rectM.Y;
                if (rect.Right > rectM.Right) rect.X = rectM.X + rectM.Width - rect.Width;
                if (rect.Bottom > rectM.Bottom) rect.Y = rectM.Y + rectM.Height - rect.Height;
            }

            if (rect.Width <= 0) rect.Width = 3;
            if (rect.Height <= 0) rect.Height = 3;
            return rect;
        }


        /// <summary>
        /// 引发 System.Windows.Forms.Form.Shown 事件。
        /// </summary>
        /// <param name="e">一个包含事件数据的 System.EventArgs。</param>
        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            this.Bounds = this.RectStart;
            this.SetRegion(this.ClipStart);
            this.m_IsSplitMoving = true;
        }
        /// <summary>
        /// 引发 System.Windows.Forms.Form.Closed 事件。
        /// </summary>
        /// <param name="e">一个包含事件数据的 System.EventArgs。</param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            this.m_IsSplitMoving = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="m">Type: ref Message</param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == Win32Msg.WM_NCHITTEST) { m.Result = (IntPtr)(-1L); return; }
            base.WndProc(ref m);
        }

        /// <summary>
        /// 引发 System.Windows.Forms.Control.MouseMove 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.MouseEventArgs。</param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            //Console.WriteLine("SSSSSSSS: OnMouseMove");
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="clip">Type: Region</param>
        protected virtual void SetRegion(Region clip)
        {
            if (clip == null) return;

            var rect = Win32API.GetWindowRectangle(this.Handle);
            var region1 = new Region(rect);
            region1.Intersect(clip);
            region1.Translate(0 - rect.X, 0 - rect.Y);

            var region2 = this.Region;
            this.Region = region1;
            if (region2 != null) { region2.Dispose(); }
        }


        #region  作 废 的 函 数

        /// <summary>
        /// 引发 System.Windows.Forms.Control.HandleCreated 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.EventArgs。</param>
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            //Win32API.DrawSplitHelper(this.Handle, new Rectangle(0, 0, this.Width, this.Height));
        }
        //protected override void OnPaint(PaintEventArgs e)
        //{
        //    try
        //    {
        //        base.OnPaint(e);
        //        //e.Graphics.Clear(Color.PaleVioletRed);
        //        //Win32API.DrawSplitHelper(this.Handle, new Rectangle(0, 0, this.Width, this.Height));
        //    }
        //    catch (Exception ex) { Tools.LogWarn2(ex, "改写 SplitterForm.OnPaint(PaintEventArgs e) 发生错误"); }
        //}
        /// <summary>
        /// 绘制控件的背景。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.PaintEventArgs。</param>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            base.OnPaintBackground(e);
            //Win32API.DrawSplitHelper(this.Handle, new Rectangle(0, 0, this.Width, this.Height));
        }
        /// <summary>
        /// 引发 System.Windows.Forms.Control.MouseDown 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 System.Windows.Forms.MouseEventArgs。</param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            //Win32API.DrawSplitHelper(this.Handle, new Rectangle(0, 0, this.Width, this.Height));
        }

        #endregion


    }

    /// <summary>
    /// 
    /// </summary>
    public struct SplitInfo
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="start">Type: Rectangle</param>
        /// <param name="end">Type: Rectangle</param>
        public SplitInfo(Rectangle start, Rectangle end)
        {
            m_Start = start;
            m_End = end;
            m_Diff = new Point(end.X - start.X, end.Y - start.Y);
        }

        /// <summary>
        /// 
        /// </summary>
        public static readonly SplitInfo Empty = new SplitInfo(Rectangle.Empty, Rectangle.Empty);


        private Rectangle m_Start;
        private Rectangle m_End;
        private Point m_Diff;


        /// <summary>
        /// 
        /// </summary>
        public Rectangle Start
        {
            get { return m_Start; }
        }
        /// <summary>
        /// 
        /// </summary>
        public Rectangle End
        {
            get { return m_End; }
        }
        /// <summary>
        /// 
        /// </summary>
        public Point Diff
        {
            get { return m_Diff; }
        }
        /// <summary>
        /// 
        /// </summary>
        public bool IsEmpty
        {
            get { return m_Diff.X <= 0 && m_Diff.Y <= 0; }
        }
    }
}
